import os
import shutil

import libreface
import pandas as pd
import time
from pathlib import Path


def process_video_files(parent_dir, output_dir, csv_path, failed_csv='failed.csv', max_retries=1):
    # 初始化失败记录文件
    if not Path(failed_csv).exists():
        pd.DataFrame(columns=['name']).to_csv(failed_csv, index=False)
        print(f"新建失败记录文件: {failed_csv}")

    # 加载必须处理的名单
    try:
        df_required = pd.read_csv(csv_path)
        required = set(df_required['name'].str.lower().str.strip())
    except Exception as e:
        print(f"白名单加载失败: {str(e)}")
        return

    # 加载历史失败记录（带错误处理）
    try:
        df_failed = pd.read_csv(failed_csv)
        failed = set(df_failed['name'].str.lower().str.strip())
    except Exception as e:
        print(f"加载失败记录出错: {str(e)}，将创建新记录")
        failed = set()
        pd.DataFrame(columns=['name']).to_csv(failed_csv, index=False)

    # 扫描已存在的特征文件
    existing = set()
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    for f in output_dir.glob('*_features.csv'):
        base = f.stem.split('_features')[0].lower().strip()
        existing.add(base)

    # 构建最终处理列表
    process_list = []
    for root, _, files in os.walk(parent_dir):
        for f in files:
            if f.lower().endswith(('.mp4', '.avi', '.mov')):
                base = Path(f).stem.lower().strip()
                if all([
                    base in required,
                    base not in existing,
                    base not in failed
                ]):
                    process_list.append(Path(root) / f)

    # 处理核心逻辑
    for idx, video_path in enumerate(process_list, 1):
        base = video_path.stem
        output_path = output_dir / f"{base}_features.csv"

        print(f"Processing ({idx}/{len(process_list)}) {video_path.name}")

        success = False
        for attempt in range(max_retries):
            try:
                # 清理临时目录
                temp_dir = Path("temp")
                if temp_dir.exists():
                    shutil.rmtree(temp_dir)

                # 执行处理
                libreface.get_facial_attributes(
                    str(video_path),
                    output_save_path=str(output_path),
                    temp_dir="temp"
                )

                # 增强型结果验证
                if output_path.exists():
                    if output_path.stat().st_size > 1024:  # 文件大小验证
                        try:
                            pd.read_csv(output_path)  # 尝试解析CSV验证格式
                            success = True
                            break
                        except:
                            print("生成的CSV文件格式无效")
                    else:
                        print("生成的CSV文件过小")
                else:
                    print("输出文件未生成")

                #time.sleep(2 ** attempt)  # 指数退避

            except Exception as e:
                print(f"尝试 {attempt + 1} 失败: {str(e)}")

        # 记录最终结果
        if not success:
            print(f"永久失败: {base}")
            try:
                with open(failed_csv, 'a') as f:
                    f.write(f"{base}\n")
            except Exception as e:
                print(f"记录失败信息出错: {str(e)}")
        else:
            print(f"成功生成: {output_path}")


if __name__ == '__main__':
    process_video_files(
        parent_dir='',
        output_dir='test',
        csv_path='1.csv',
        failed_csv='./data/failed_records.csv'
    )